package com.toplabs.unashu.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.lionsoul.ip2region.xdb.Searcher;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author toplabs
 * @since 2022/11/21
 * <p>This java file was created by toplabs in 2022/11/21.
 * The following is the description information about this file:</p>
 * <p>description:IP相关工具类</p>
 */
@Slf4j
public class IPUtils {

    private IPUtils() {
        throw new IllegalStateException("Utility class");
    }

    private static final String UNKNOWN = "unknown";
    private static final String UNKNOWN_HOST_EXCEPTION = "UnknownHostException";

    /**
     * 获取当前的IP
     *
     * @param request HttpServletRequest
     * @return String
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (TopLabsUtils.isEmpty(ipAddress) || UNKNOWN.equals(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (TopLabsUtils.isEmpty(ipAddress) || UNKNOWN.equals(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (TopLabsUtils.isEmpty(ipAddress) || UNKNOWN.equals(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if ("127.0.0.1".equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) {
                // 根据网卡取本机配置的IP
                InetAddress inet;
                try {
                    inet = InetAddress.getLocalHost();
                    ipAddress = inet.getHostAddress();
                } catch (UnknownHostException e) {
                    log.error(UNKNOWN_HOST_EXCEPTION, e);
                }
            }
        }
        //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割  //"***.***.***.***".length() = 15
        if (ipAddress != null && ipAddress.length() > 15) {
            int index = ipAddress.indexOf(",");
            if (index > 0) {
                ipAddress = ipAddress.substring(0, index);
            }
        }
        return ipAddress;
    }

    public static String getCityInfo(String ip) {
        String dbPath = TopLabsUtils.getFilePath("/ip2region/ip2region.xdb");
        File file = new File(dbPath);
        try {
            if (!file.exists()) {
                log.error("Error: Invalid ip2region.db file");
                String tmpDir = System.getProperties().getProperty("java.io.tmpdir");
                dbPath = tmpDir + "ip.db";
                file = new File(dbPath);
                FileUtils.copyInputStreamToFile(Objects.requireNonNull(IPUtils.class.getClassLoader().getResourceAsStream("classpath:ip2region/ip2region.xdb")), file);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Searcher searcher = null;
        try {
            searcher = Searcher.newWithFileOnly(dbPath);
            if (!isIpAddress(ip)) {
                log.error("Error: Invalid ip address");
            }
            String ipInfo = searcher.search(ip);
            if (!TopLabsUtils.isEmpty(ipInfo)) {
                ipInfo = ipInfo.replace("|0", "");
                ipInfo = ipInfo.replace("0|", "");
            }
            return ipInfo;
        } catch (Exception e) {
            log.error("Exception:", e);
        } finally {
            if (searcher != null) {
                try {
                    searcher.close();
                } catch (IOException e) {
                    log.error("Searcher close error:", e);
                }
            }
        }
        return null;
    }

    /**
     * 获取IP
     *
     * @return String
     */
    public static String getHostIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            log.error(UNKNOWN_HOST_EXCEPTION, e);
        }
        return "127.0.0.1";
    }

    /**
     * 获取主机名
     *
     * @return String
     */
    public static String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            log.error(UNKNOWN_HOST_EXCEPTION, e);
        }
        return "未知";
    }

    /**
     * 验证IP字符串是否合规
     *
     * @param ip ip字符串
     * @return true标识合规
     */
    public static boolean isIpAddress(String ip) {
        String pattern = "((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(ip);
        return m.matches();
    }

    public static void main(String[] args) {
        String ip = "117.136.104.144";
        String cityIpString = getCityInfo(ip);
        log.debug(cityIpString);
    }
}
